/*
 * LineManager.cpp
 *
 *  Created on: 2012-9-9
 *      Author: yangentao@gmail.com
 */

#include "LineManager.h"

LineManager::LineManager() {
	vec.append(0);
	vec.append(INT_MAX); //the last element , usefull
}
void LineManager::dump() {
	cout << "Length: " << count() << endl;
	cout << "[";
	for (int i = 0; i < count(); ++i) {
		cout << vec[i] << " ";
	}
	cout << "]" << endl;
}
size_t LineManager::findLine(int position) {
	//[0**************MAX_INT]
	if (position < 0) {
		throw IndexOutOfBoundException();
	}

	int * begin = vec.getBuffer();
	int * end = begin + vec.size();

	int* first = lower_bound(begin, end, position);

	if (first != end) {
		if (first == begin) {
			return 0;
		}
		if (*first == position) {
			return first - begin;
		} else {
			return first - begin - 1;
		}
	}
	throw NotFoundException();
	return 0;
}
void LineManager::parseCrLf(const String& text, Vector<int>& lines, int delta) {
	for (int i = 0; i < text.length(); ++i) {
		if (text[i] == 13) { // no \n fllow by \r
			if (i + 1 < text.length()) {
				if (text[i + 1] != 10) {
					lines.append(i + delta);
				}
			}
		} else if (text[i] == 10) {
			lines.append(i + delta);
		}
	}
}

void LineManager::onTextReplaced(int from, int oldTextLength, const String& newText) {
	if(from <0 || oldTextLength<0){
		throw NegtiveIndexException();
	}
	//
	int lineto = findLine(from + oldTextLength);
	int delta = newText.length() - oldTextLength;
	//[lineto +1, count) has no effect
	if (lineto + 1 < count()) {
		vec.rangeAdd(lineto+1, count(), delta);
	}

	Vector<int> newlines;
	parseCrLf(newText, newlines, from + 1);

	int linefrom = findLine(from);	//exclude linefrom
//	vec.dump();
//	newlines.dump();
//	cerr << "replace(" << (linefrom + 1) << ", " << (max(0, lineto - linefrom)) << ", xxx, " << newlines.size() << ")" << endl;
	vec.replace(linefrom + 1, max(0, lineto - linefrom), newlines.getBuffer(), newlines.size());
//	vec.dump();
}
